package com.TeacherInfoServer.common.service.Impl;

import com.TeacherInfoServer.common.Result;
import com.TeacherInfoServer.pojo.DTO.AddDoctoralSupervisorDTO;
import com.TeacherInfoServer.pojo.DTO.SearchDTO.DoctoralSupervisorSearchDTO;
import com.TeacherInfoServer.pojo.DTO.UpdateDoctoralSupervisorDTO;
import com.TeacherInfoServer.pojo.entity.DoctoralSupervisor;
import com.TeacherInfoServer.pojo.vo.DoctoralSupervisorListVo;
import com.TeacherInfoServer.pojo.vo.DoctoralSupervisorVo;
import com.TeacherInfoServer.exception.JobNumberNotExistException;
import com.TeacherInfoServer.exception.RecordExistException;
import com.TeacherInfoServer.mapper.DoctoralSupervisorMapper;
import com.TeacherInfoServer.common.service.DoctoralSupervisorService;
import com.TeacherInfoServer.common.service.TeacherService;
import com.TeacherInfoServer.utils.HttpServletUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DoctoralSupervisorServiceImpl extends ServiceImpl<DoctoralSupervisorMapper, DoctoralSupervisor> implements DoctoralSupervisorService {

    @Autowired
    private DoctoralSupervisorMapper doctoralSupervisorMapper;
    @Autowired
    private TeacherService teacherService;


    @Override
    @Transactional
    public Result<Map<String, Integer>> addOne(AddDoctoralSupervisorDTO addDoctoralSupervisorDTO) {
        LambdaQueryWrapper<DoctoralSupervisor> wrapper = new LambdaQueryWrapper<>();
        if (doctoralSupervisorMapper.selectOne(wrapper.eq(DoctoralSupervisor::getTeacherId, addDoctoralSupervisorDTO.getTeacherId())) == null){
            if (teacherService.getOne(addDoctoralSupervisorDTO.getTeacherId()).getData() != null){
                DoctoralSupervisor doctoralSupervisor =
                        new DoctoralSupervisor(null,
                                addDoctoralSupervisorDTO.getTeacherId(),
                                addDoctoralSupervisorDTO.getObtainDate(),
                                addDoctoralSupervisorDTO.getObtainSchool(),1,null);
                Integer record = doctoralSupervisorMapper.insert(doctoralSupervisor);
                Map<String,Integer> map = new HashMap<>();
                map.put("record",record);
                return Result.success(map);
            } else {
                throw new JobNumberNotExistException();
            }
        } else {
            throw new RecordExistException();
        }
    }

    @Override
    @Transactional
    public Result<DoctoralSupervisorListVo> getList(Long pageNumber, Long pageSize) {
        Page<DoctoralSupervisor> page = new Page<>(pageNumber,pageSize);
        List<DoctoralSupervisor> doctoralSupervisorList = doctoralSupervisorMapper.selectPageWithTeacher(page);
        List<DoctoralSupervisorVo> doctoralSupervisorVoList = getDoctoralSupervisorVoList(doctoralSupervisorList);
        DoctoralSupervisorListVo doctoralSupervisorListVo =
                new DoctoralSupervisorListVo(page.getCurrent(),
                        page.getSize(),
                        page.getPages(),
                        page.getTotal(),
                        doctoralSupervisorVoList);
        return Result.success(doctoralSupervisorListVo);
    }

    @Override
    public Map<String,Object> searchDoctoralSupervisorList(DoctoralSupervisorSearchDTO doctoralSupervisorSearchDTO){
        Page<DoctoralSupervisorVo> page = new Page<>(doctoralSupervisorSearchDTO.getPages(), doctoralSupervisorSearchDTO.getSize());
        doctoralSupervisorMapper.searchDoctorSupervisorList(page,doctoralSupervisorSearchDTO);
        Map<String, Object> data = new HashMap<>();
        data.put("totals",page.getTotal());
        data.put("currentPages",page.getCurrent());
        data.put("pageNumber",page.getPages());
        data.put("rows",page.getRecords());
        return data;
    }

    @Override
    public void export(HttpServletResponse response, String fileName) throws IOException {
        HttpServletUtil.setExportResponse(response,fileName);
        List<DoctoralSupervisor> doctoralSupervisorList = doctoralSupervisorMapper.selectPageWithTeacher(null);
        List<DoctoralSupervisorVo> doctoralSupervisorVoList = getDoctoralSupervisorVoList(doctoralSupervisorList);
        EasyExcel.write(response.getOutputStream(), DoctoralSupervisorVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(doctoralSupervisorVoList);
    }

    @Override
    @Transactional
    public Result<Map<String, Integer>> deleteBatch(String[] teacherIds) {
        LambdaQueryWrapper<DoctoralSupervisor> wrapper = new LambdaQueryWrapper<>();
        Integer record = doctoralSupervisorMapper.delete(wrapper.in(DoctoralSupervisor::getTeacherId, Arrays.asList(teacherIds)));
        Map<String, Integer> map = new HashMap<>();
        map.put("record", record);
        return Result.success(map);
    }

    @Override
    @Transactional
    public Result<Map<String, Integer>> updateOne(UpdateDoctoralSupervisorDTO updateDoctoralSupervisorDTO) {
        LambdaUpdateWrapper<DoctoralSupervisor> updateWrapper = new LambdaUpdateWrapper<>();
        int record;
        if (teacherService.getOne(updateDoctoralSupervisorDTO.getTeacherId()).getData() != null){
            record = doctoralSupervisorMapper.update(null,updateWrapper.eq(DoctoralSupervisor::getId, updateDoctoralSupervisorDTO.getId())
                    .set(DoctoralSupervisor::getTeacherId, updateDoctoralSupervisorDTO.getTeacherId())
                    .set(DoctoralSupervisor::getObtainDate, updateDoctoralSupervisorDTO.getObtainDate())
                    .set(DoctoralSupervisor::getObtainSchool, updateDoctoralSupervisorDTO.getObtainSchool()));
        } else {
            throw new JobNumberNotExistException();
        }
        LambdaQueryWrapper<DoctoralSupervisor> queryWrapper = new LambdaQueryWrapper<>();
        if (doctoralSupervisorMapper.selectList(queryWrapper.eq(DoctoralSupervisor::getTeacherId, updateDoctoralSupervisorDTO.getTeacherId())).size() > 1){
            throw new RecordExistException();
        }
        Map<String, Integer> map = new HashMap<>();
        map.put("record", record);
        return Result.success(map);
    }

    private List<DoctoralSupervisorVo> getDoctoralSupervisorVoList(List<DoctoralSupervisor> doctoralSupervisorList){
        return doctoralSupervisorList.stream()
                .map(doctoralSupervisor -> new DoctoralSupervisorVo(
                        doctoralSupervisor.getId(),
                        doctoralSupervisor.getTeacherId(),
                        doctoralSupervisor.getTeacher().getTeacherName(),
                        doctoralSupervisor.getObtainDate(),
                        doctoralSupervisor.getObtainSchool()
                ))
                .collect(Collectors.toList());
    }
}
